import {
  router
} from "./router.js";
import authorize from './modules/authorize.js';
import {
  debounce,
  formatRequestData,
  jsonToQuery,
  isEmpty
} from "./newUtil.js";
import { getStorageSync, removeStorageSync, setStorageSync } from "./compatible.js";
/**
 * 系统调用接口配置
 */
const api = {
  // 解析域名
  domain: "beta.366ec.net",
  //h5域名 
  h5Domain: "http://m.beta.366ec.net",
  // 接口主机 
  host: "http://beta.366ec.net",
  // 图片域名 
  imgDomain: "http://gateway.beta.366ec.net/image",
  // 视频域名 
  videoDomain: "http://gateway.beta.366ec.net/video",
  //是否开启oss
  enableOss: true,
  //网关域名
  gwDomain: "https://gateway.beta.366ec.net",
  //抓包的api
  wiresharkApi: "/visit.do", //"/das/ppc",
  ScantyMobile: '', //缺货登记手机号
  // // 解析域名
  // domain: "release.366ec.net", 
  // //h5域名 
  // h5Domain: "http://m.release.366ec.net", 
  // // 接口主机 
  // host: "http://release.366ec.net", 
  // // 图片域名 
  // imgDomain: "http://gateway.release.366ec.net/image",  
  // // 视频域名 
  // videoDomain: "http://gateway.release.366ec.net/video",  
  // //是否开启oss 
  // enableOss:true,
  // //网关域名
  // gwDomain: "https://gateway.release.366ec.net",
  // //抓包的api 
  // wiresharkApi: "/visit.do",  //"/das/ppc",

  // 解析域名
  // domain: "km2.366kmpf.com",
  // //h5域名
  // h5Domain: "https://m.km2.366kmpf.com",
  //  // 域名
  // host: "https://km2.366kmpf.com",
  //  // 图片域名
  // imgDomain: 'https://img.366kmpf.com',
  // //是否开启oss
  // enableOss: true,
  // //网关域名
  // gwDomain:"https://gw.366kmpf.com",
  // //抓包的api
  // wiresharkApi: "/das/ppc",

  //导航标题
  title: "",
  titleColor: "#e56b14",
  webSite: {
    logo: "",
    bgPic: ""
  },
  Currency: "￥",
  path: "/Route.axd",

  version: "2.0",

  serviceKey: "vast",

  appId: "4a364f2d1f1fb842",

  secret: "0a2b7ae94a364f2d1f1fb8423e9efd00",

  //地图key
  amapKey: "",
  //发布版本
  publicVersion: "1.0",
  timeoutCode: -10000,
  projectDir: '' // 当前线路
}

/**
 * 对JS中的字符串进行方法扩展
 * @param bit: 得到指定位数的加密串,默认16位
 * @exmple: "tt".md5(); "tt".md5(32);
 */
String.prototype.md5 = function (bit) {
  var sMessage = this;

  function rotateLeft(lValue, iShiftBits) {
    return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
  }

  function addUnsigned(lX, lY) {
    var lX4, lY4, lX8, lY8, lResult;
    lX8 = (lX & 0x80000000);
    lY8 = (lY & 0x80000000);
    lX4 = (lX & 0x40000000);
    lY4 = (lY & 0x40000000);
    lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
    if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
    if (lX4 | lY4) {
      if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
      else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
    } else return (lResult ^ lX8 ^ lY8);
  }

  function F(x, y, z) {
    return (x & y) | ((~x) & z);
  }

  function G(x, y, z) {
    return (x & z) | (y & (~z));
  }

  function H(x, y, z) {
    return (x ^ y ^ z);
  }

  function I(x, y, z) {
    return (y ^ (x | (~z)));
  }

  function FF(a, b, c, d, x, s, ac) {
    a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac));
    return addUnsigned(rotateLeft(a, s), b);
  }

  function GG(a, b, c, d, x, s, ac) {
    a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac));
    return addUnsigned(rotateLeft(a, s), b);
  }

  function HH(a, b, c, d, x, s, ac) {
    a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac));
    return addUnsigned(rotateLeft(a, s), b);
  }

  function II(a, b, c, d, x, s, ac) {
    a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac));
    return addUnsigned(rotateLeft(a, s), b);
  }

  function convertToWordArray(sMessage) {
    var lWordCount;
    var lMessageLength = sMessage.length;
    var lNumberOfWords_temp1 = lMessageLength + 8;
    var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
    var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
    var lWordArray = Array(lNumberOfWords - 1);
    var lBytePosition = 0;
    var lByteCount = 0;
    while (lByteCount < lMessageLength) {
      lWordCount = (lByteCount - (lByteCount % 4)) / 4;
      lBytePosition = (lByteCount % 4) * 8;
      lWordArray[lWordCount] = (lWordArray[lWordCount] | (sMessage.charCodeAt(lByteCount) <<
        lBytePosition));
      lByteCount++;
    }
    lWordCount = (lByteCount - (lByteCount % 4)) / 4;
    lBytePosition = (lByteCount % 4) * 8;
    lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
    lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
    lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
    return lWordArray;
  }

  function wordToHex(lValue) {
    var WordToHexValue = "",
      WordToHexValue_temp = "",
      lByte, lCount;
    for (lCount = 0; lCount <= 3; lCount++) {
      lByte = (lValue >>> (lCount * 8)) & 255;
      WordToHexValue_temp = "0" + lByte.toString(16);
      WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2);
    }
    return WordToHexValue;
  }
  var x = Array();
  var k, AA, BB, CC, DD, a, b, c, d
  var S11 = 7,
    S12 = 12,
    S13 = 17,
    S14 = 22;
  var S21 = 5,
    S22 = 9,
    S23 = 14,
    S24 = 20;
  var S31 = 4,
    S32 = 11,
    S33 = 16,
    S34 = 23;
  var S41 = 6,
    S42 = 10,
    S43 = 15,
    S44 = 21;
  // Steps 1 and 2. Append padding bits and length and convert to words 
  x = convertToWordArray(sMessage);
  // Step 3. Initialise 
  a = 0x67452301;
  b = 0xEFCDAB89;
  c = 0x98BADCFE;
  d = 0x10325476;
  // Step 4. Process the message in 16-word blocks 
  for (k = 0; k < x.length; k += 16) {
    AA = a;
    BB = b;
    CC = c;
    DD = d;
    a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
    d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
    c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
    b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
    a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
    d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
    c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
    b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
    a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
    d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
    c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
    b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
    a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
    d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
    c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
    b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
    a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
    d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
    c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
    b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
    a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
    d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
    c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
    b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
    a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
    d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
    c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
    b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
    a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
    d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
    c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
    b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
    a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
    d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
    c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
    b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
    a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
    d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
    c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
    b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
    a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
    d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
    c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
    b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
    a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
    d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
    c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
    b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
    a = II(a, b, c, d, x[k + 0], S41, 0xF4292244);
    d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
    c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
    b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
    a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
    d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
    c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
    b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
    a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
    d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
    c = II(c, d, a, b, x[k + 6], S43, 0xA3014314);
    b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
    a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
    d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
    c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
    b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
    a = addUnsigned(a, AA);
    b = addUnsigned(b, BB);
    c = addUnsigned(c, CC);
    d = addUnsigned(d, DD);
  }
  if (bit == 32) {
    return wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
  } else {
    return wordToHex(b) + wordToHex(c);
  }
};

/**
 * 根据字典获取签名
 * param: 数据字典
 */
function getSign(dict) {
  var itmes = [];
  Object.keys(dict).map(function (key) {
    if ((typeof (dict[key]) == "string" && dict[key] != "") || (typeof (dict[key]) != "string")) {
      itmes.push(key + "=" + encodeURIComponent(dict[key]));
    }
  });
  // console.log(itmes);
  var sortAry = itmes.sort(function (a, b) {
    return a.toLowerCase().localeCompare(b.toLowerCase());
  });
  // console.log(sortAry);
  var parameters = itmes.join("&") + "&secret=" + api.secret;
  // console.log("-------parameters------------");
  // console.log(parameters);
  return parameters.md5(32);
}
const util = {
  /**
   * 用get的方式获取远程数据
   * param: 远程地址路径
   * param: 回调方法
   * param: 请求头部信息参数对象
   * param: 是否显示加载中的提示
   */
  get: function (path, callback, headerParam, isLoading = true) {
    if (isLoading) {
      wx.showToast({
        title: '数据加载中',
        icon: 'loading'
      });
    }

    wx.request({
      url: path,
      header: {},
      method: 'GET',
      dataType: 'json',
      responseType: 'text',
      success: res => {
        //console.log(res.data);
        if (typeof (callback) == "function") {
          callback.apply(this, [res]);
        }
        if (isLoading) {
          wx.hideToast();
        }
      },
      fail: function(res) {
        console.log('get数据失败，请求如下：')
        console.log(path)
        console.error(res);
        if (isLoading) {
          wx.hideToast();
        }
      },
      complete: function (res) {
        // todo
      },
    });
  },
  /**
   * Post方式请求接口数据
   * param: 请求的接口名
   * param: post需要发送的数据
   * param: 回调方法
   * param: 请求时需要追加的头部信息
   * param: 是否显示加载中的提示
   * param: cacheType, 0-不使用缓存,1-使用缓存根据缓存时间失效, 2-使用缓存,先给出缓存值回调callback,然后立即再取数据,获取数据后再回调callback
   */
  post: async function(apiName, data, callback, version, headerParam, isLoading = true, cacheType=0,hasKey=true) {
    var cacheKey = "";
    var key = hasKey ? api.serviceKey + "." : "";
    // 判断当前接口访问是否使用缓存机制
    if (cacheType > 0) {
      cacheKey = key + apiName + "_" + JSON.stringify(data).md5(32);

      var val = storage.get(cacheKey)
      if (val) {
        if (typeof (callback) == "function") {
          try {
            val.isCache = true;
            callback.apply(this, [val]);
          } catch (e) {
            console.error(e);
          };
          // 当缓存类型为1时无需再走请求
          if (cacheType == 1) {
            return;
          }
        }
      }
    }

    // if (isLoading) {
    //   wx.showToast({
    //     title: '数据加载中',
    //     icon: 'loading'
    //   });
    // }
    var openid = getStorageSync('openid');
    var items = data; //Object.create(data);
    var entity = authorize.getEntity();
    items["v"] = version || api.version;
    items["method"] = key + apiName;
    items["appid"] = api.appId;
    items["timestamp"] = Math.round(new Date().getTime() / 1000);
    items["sign"] = getSign(items);
    // items["Token"] = entity?entity.manager.Token:'';
    var header = {
      'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
      'version': '3.3.600',
      'Platform': 'Weapp',
      'terminalId': '5',
      'DeviceNo': openid
      // 'gsp': 'developer'  //正式灰度包
    };
    let url = api.host + api.path
    let method = api.serviceKey + "." + apiName
    if (this.needForProjectDir(method) && api.projectDir) {
      url = `${api.host}/${api.projectDir}${api.path}`
    }
    wx.request({
      url: url,
      data: items,
      header: header,
      method: 'POST',
      dataType: 'json',
      responseType: 'text',
      timeout: 30 * 1000, //设置超时时间
      success: res => {
        logRequest(items, res)
        if (cacheType > 0 && cacheKey !== "") {
          storage.put(cacheKey, res);
        }
        if (res.data.Code == 4004 || res.data.Code == 4014 || res.data.Code == 4141) {
          toLoginPage(res)
          return
        }
        if (res.data.Code == 4040 || res.data.Code == 4041) {
          util.tips(res.Message);
        }
        if (typeof (callback) == "function") {
          callback.apply(this, [res]);
        }

        // if (isLoading) {
        //   wx.hideToast();
        // }
      },
      fail: function (res) {
        // if (isLoading) {
        //   wx.hideToast();
        // }
        console.log('post数据失败，请求如下：')
        console.log(url, items, header)
        console.log(res)
        if ((res.errMsg == "request:fail timeout" || res.errMsg.indexOf("time out")>-1) && typeof (callback) == "function") {
          var res_dic = {
            Code: api.timeoutCode,
            Success: false,
            Message: "sorry,网络超时！"
          }
          //util.tips(res_dic.Message);
          callback.apply(this, [{
            data: res_dic
          }]);

        } else {
          console.log(res.errMsg);
          //util.alert(res.errMsg);
        }

        util.post_api_err(res, items);

      },
      complete: function (res) {
        // todo
      },
    });
  },
  /**
   * 
   */
  fetch: async(apiName, data, callback, ver = '2.0', methodType = 'POST', dataType = 'json', header = {}, isLoading = true) => {
    // if (isLoading) {
    //   wx.showToast({
    //     title: '数据加载中',
    //     icon: 'loading'
    //   });
    // }

    if (typeof (header) != "object") {
      header = {
        'Content-Type': 'application/x-www-form-urlencoded'
      };
    } else {
      header["Content-Type"] = 'application/x-www-form-urlencoded';
    }
    var openid = getStorageSync('openid');
    header['version'] = '3.3.600';
    header['Platform'] = 'Weapp';
    header['terminalId'] = '5';
    header['DeviceNo'] = openid;

    data["v"] = ver || api.version;
    data["method"] = api.serviceKey + "." + apiName;
    data["appid"] = api.appId;
    data["timestamp"] = Math.round(new Date().getTime() / 1000);
    data["sign"] = getSign(data);

    let url = api.host + api.path
    let method = api.serviceKey + "." + apiName
    if (util.needForProjectDir(method) && api.projectDir) {
      url = `${api.host}/${api.projectDir}${api.path}`
    }
    wx.request({
      url: url,
      data: data,
      header: header,
      method: methodType,
      dataType: dataType,
      responseType: 'text',
      success: res => {
        // wx.hideNavigationBarLoading();
        // console.log(res.data);
        /**
         * Function.call(obj,[param1[,param2[,…[,paramN]]]])
            obj：这个对象将代替Function类里this对象
            params：这个是一个参数列表
         */
        if (typeof (callback) == "function") {
          callback.apply(this, [res]);
        }
        // if (isLoading) {
        //   wx.hideToast();
        // }
      },
      fail: function (res) {
        // if (isLoading) {
        //   wx.hideToast();
        // }
        console.log('fetch数据失败，请求如下：')
        console.log(url, data, header)
        console.log(res)
        if ((res.errMsg == "request:fail timeout" || res.errMsg.indexOf("time out") > -1) && typeof (callback) == "function") {
          var res_dic = {
            Code: api.timeoutCode,
            Success: false,
            Message: "sorry,网络超时！"
          }
          //util.tips(res_dic.Message);
          callback.apply(this, [{
            data: res_dic
          }]);

        }
        util.post_api_err(res, data);
      },
      complete: function (res) {
        // todo
      },
    });
  },
  /**发送api错误信息 */
  post_api_err(res, items) {
    var msg_error = res.errMsg;
    var error_data = {
      AppKey: api.secret,
      ApiDomain: api.domain,
      Terminal: "WXApp",
      PageTitle: "小程序异常监测",
      PageKey: "minpro_error_api",
      ViewTime: new Date().getTime(),
      Version: api.publicVersion,
      Parameter: {
        error_msg: msg_error
      }
    }
    for (var item in items) {
      var value = items[item];
      error_data[item] = value;
    }
    if (items["method"]) {
      error_data.PageTitle = error_data.PageTitle + items["method"];
    }
    console.log("post----" + error_data);
    //异常检测
    util.post_api(api.host + api.wiresharkApi, error_data);
  },
  /**
   * post到api最基础
   */
  post_api(api_url, items, callback) {
    var header = {
      'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
      'Platform': 'Weapp'
    };
    wx.request({
      url: api_url,
      data: JSON.stringify(items),
      header: header,
      method: 'POST',
      dataType: 'json',
      responseType: 'text',
      success: res => {
        if (callback && typeof (callback) == "function") {
          callback.apply(this, [res]);
        }
      },
      fail: function (res) {
        console.log('post_api数据失败，请求如下：')
        console.log(api_url, items, header)
        console.log(res)
        console.log(res.errMsg);
      },
      complete: function (res) {
        // todo
      },
    })
  },
  /**
   * 提示信息
   */
  tips: function (title, duration) {
    wx.showToast({
      title: title,
      icon: 'none',
      duration: duration || 2000
    });
  },

  /**
   * 
   */
  success: function (title, callback, duration) {
    wx.showToast({
      title: title,
      icon: 'success',
      //image: '',
      duration: duration || 2000,
      mask: true,
      success: function (res) {

      },
      fail: function (res) {},
      complete: function (res) {
        if (typeof (callback) == "function") {
          callback.apply(this, [res]);
        }
      },
    })
  },

  confirm: function (okCallback, cancelCallback, content, title, okText, cancelText) {
    if (typeof (content) == "object") {
      content = "数据格式不正确";
    }
    wx.showModal({
      title: title || '快马批发',
      content: content || '您确定要做此操作吗',
      confirmText: okText || "确定",
      cancelText: cancelText || "取消",
      success: function (res) {
        // console.log(res);
        if (res.confirm) {
          if (typeof (okCallback) == 'function') {
            okCallback.apply(this, [res]);
          }
          // console.log('用户点击主操作')
        } else {
          console.log('用户点击辅助操作')
        }
      }
    });
  },

  alert: function (content, title, callback) {
    if (typeof (content) == "object") {
      content = "数据格式不正确";
    }
    if (content) {
      wx.showModal({
        title: title || "提示",
        content: content || '请输入正确的格式',
        showCancel: false,
        success: function (res) {
          if (res.confirm) {
            if (typeof (callback) == 'function') {
              callback.apply(this, [res]);
            }
          }
        }
      });
    }
  },
  /**
   * 增加分、时、天
   */
  addTime: (n, t = 1, date = new Date()) => {
    date = date || new Date();
    //下面的不是时间戳，是时间戳*1000
    var timestamp = Date.parse(date);
    var tamp = 0;
    if (t == 0) {
      //分钟
      tamp = n * 60 * 1000;
    } else if (t == 1) {
      //小时
      tamp = n * 60 * 60 * 1000;
    } else if (t == 2) {
      //天数
      tamp = n * 24 * 60 * 60 * 1000;
    }
    var newTimestamp = timestamp + tamp;
    return new Date(newTimestamp);
  },
  /**
   * 格式化日期
   */
  formatTime: function (date) {
    const year = date.getFullYear()
    const month = date.getMonth() + 1
    const day = date.getDate()
    const hour = date.getHours()
    const minute = date.getMinutes()
    const second = date.getSeconds()

    return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
  },
  getNowDate: function (date) {
    const year = date.getFullYear()
    const month = date.getMonth() + 1
    const day = date.getDate()

    return [year, month, day].map(this.formatNumber).join('-')
  },
  getDateSt(today, addDayCount, showtype) { //返回需要的几天前的日期
    var date;
    if (today) {
      date = new Date(today);
    } else {
      date = new Date();
    }
    date.setDate(date.getDate() - addDayCount); //获取AddDayCount天前的日期
    var year = date.getFullYear();
    var month = date.getMonth() + 1; //获取当前月份的日期 
    var day = date.getDate();
    var hour = date.getHours()
    var minute = date.getMinutes()
    var second = date.getSeconds()
    if (showtype == 'date')
      return [year, month, day].map(this.formatNumber).join('-')
    else
      return [year, month, day].map(this.formatNumber).join('-') + ' ' + [hour, minute, second].map(this.formatNumber).join(':')
  },
  /**
   * 日期计算
   * num:与当前日期的间隔天数   如：1明天   -1昨天
   * str:分割方式
   */
  formatGetTime: function (num, str) {
    var today = new Date();
    var nowTime = today.getTime();
    var ms = 24 * 3600 * 1000 * num;
    today.setTime(parseInt(nowTime + ms));
    var oYear = today.getFullYear();
    var oMoth = (today.getMonth() + 1).toString();
    if (oMoth.length <= 1) oMoth = '0' + oMoth;
    var oDay = today.getDate().toString();
    if (oDay.length <= 1) oDay = '0' + oDay;
    return oYear + str + oMoth + str + oDay;
  },
  /**
   * 格式化数字
   */
  formatNumber: function (n) {
    n = n.toString()
    return n[1] ? n : '0' + n
  },
  formatFloat: function (value, appoint) {
    value = value || 0;
    if (isNaN(value)) {
      return value;
    }
    return value.toFixed(appoint) //此处2为保留两位小数 
  },
  /**
   * 向上保留指定位数
   */
  keepDecimal: function (type = 'round', value = 0, len = 2) {
    var str = (value * Math.pow(10, len)).toString();
    var regstr = "^([1-9]\\d*\.\\d{1}|0\.\\d{1})";
    var reg = new RegExp(regstr);
    var rs_match = str.match(reg);
    if (rs_match && rs_match.length > 1) {
      str = rs_match[1];
    }
    return Math[type](Number(str)) / Math.pow(10, len);
  },
  /**
   * 计算两数之差（避免精度问题）
   */
  calulateReduce: function (a, b) {
    let m = 0;
    let m1 = 0;
    let m2 = 0;
    let s1 = a.toString();
    let s2 = b.toString();
    try {
      m1 = s1.split('.')[1].length
    } catch (e) {}
    try {
      m2 = s2.split('.')[1].length
    } catch (e) {}
    m = Math.pow(10, Math.max(m1, m2));
    return ((Number(a * m) - Number(b * m)) / m);
  },
  /**
   * 计算最接近的倍数值(避免精度问题)
   */
  precisionDiv: function (a, b) {
    let m1 = 0;
    let m2 = 0;
    let s1 = a.toString();
    let s2 = b.toString();
    try {
      m1 = s1.split(".")[1].length
    } catch (e) {}
    try {
      m2 = s2.split(".")[1].length
    } catch (e) {}
    return (Number(s1.replace(".", "")) / Number(s2.replace(".", "")) * Math.pow(10, m2 - m1));
  },
  precisionX: function (a, b) {
    let m = 0;
    let s1 = a.toString();
    let s2 = b.toString();
    try {
      m += s1.split(".")[1].length
    } catch (e) {}
    try {
      m += s2.split(".")[1].length
    } catch (e) {}
    return (Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m));
  },
  /**
   * base64加密
   */
  base64_encode: function (str) {
    var c1, c2, c3;
    var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    str = this.utf8_encode(str);
    var i = 0,
      len = str.length,
      strin = '';
    while (i < len) {
      c1 = str.charCodeAt(i++) & 0xff;
      if (i == len) {
        strin += base64EncodeChars.charAt(c1 >> 2);
        strin += base64EncodeChars.charAt((c1 & 0x3) << 4);
        strin += "==";
        break;
      }
      c2 = str.charCodeAt(i++);
      if (i == len) {
        strin += base64EncodeChars.charAt(c1 >> 2);
        strin += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
        strin += base64EncodeChars.charAt((c2 & 0xF) << 2);
        strin += "=";
        break;
      }
      c3 = str.charCodeAt(i++);
      strin += base64EncodeChars.charAt(c1 >> 2);
      strin += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
      strin += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
      strin += base64EncodeChars.charAt(c3 & 0x3F)
    }
    return strin
  },
  /**
   * base64解密
   */
  base64_decode: function (input) {
    var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;
    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
    while (i < input.length) {
      enc1 = base64EncodeChars.indexOf(input.charAt(i++));
      enc2 = base64EncodeChars.indexOf(input.charAt(i++));
      enc3 = base64EncodeChars.indexOf(input.charAt(i++));
      enc4 = base64EncodeChars.indexOf(input.charAt(i++));
      chr1 = (enc1 << 2) | (enc2 >> 4);
      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
      chr3 = ((enc3 & 3) << 6) | enc4;
      output = output + String.fromCharCode(chr1);
      if (enc3 != 64) {
        output = output + String.fromCharCode(chr2);
      }
      if (enc4 != 64) {
        output = output + String.fromCharCode(chr3);
      }
    }
    return this.utf8_decode(output);
  },
  utf8_encode: function (string) {
    string = string.replace(/\r\n/g, "\n");
    var utftext = "";
    for (var n = 0; n < string.length; n++) {
      var c = string.charCodeAt(n);
      if (c < 128) {
        utftext += String.fromCharCode(c);
      } else if ((c > 127) && (c < 2048)) {
        utftext += String.fromCharCode((c >> 6) | 192);
        utftext += String.fromCharCode((c & 63) | 128);
      } else {
        utftext += String.fromCharCode((c >> 12) | 224);
        utftext += String.fromCharCode(((c >> 6) & 63) | 128);
        utftext += String.fromCharCode((c & 63) | 128);
      }

    }
    return utftext;
  },
  /**
   * utf-8解密
   */
  utf8_decode: function (utftext) {
    var string = '';
    let i = 0;
    let c = 0;
    let c1 = 0;
    let c2 = 0;
    while (i < utftext.length) {
      c = utftext.charCodeAt(i);
      if (c < 128) {
        string += String.fromCharCode(c);
        i++;
      } else if ((c > 191) && (c < 224)) {
        c1 = utftext.charCodeAt(i + 1);
        string += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
        i += 2;
      } else {
        c1 = utftext.charCodeAt(i + 1);
        c2 = utftext.charCodeAt(i + 2);
        string += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63));
        i += 3;
      }
    }
    return string;
  },
  /**
   * 合并两个json
   */
  mergeJsonObject: function (jsonbject1, jsonbject2) {
    var resultJsonObject = {};
    for (var attr in jsonbject1) {
      resultJsonObject[attr] = jsonbject1[attr];
    }
    for (var attr in jsonbject2) {
      resultJsonObject[attr] = jsonbject2[attr];
    }
    return resultJsonObject;
  },
  /**
   * 获取随机字符串，32位以下
   */
  getRandomString: function () {
    return Math.random().toString(36).substring(3, 8);
  },
  /**
   * 获取当前时间戳
   */
  getCurrentTimeStamp: function () {
    var timestamp = Date.parse(new Date());
    return timestamp + "";
  },
  /**去掉首尾空格 */
  trim: function (str) {
    if (str == undefined) return "";
    if (str.length <= 0) return str;
    return str.replace(/(^\s*)|(\s*$)/g, "");
  },
  /** 解析Url链接参数 */
  urlParse: function (url) {
    let obj = {};
    let reg = /[?&][^?&]+=[^?&]+/g
    let arr = url.match(reg)
    if (arr) {
      arr.forEach((item) => {
        let tempArr = item.substr(1).split('=')
        let key = decodeURIComponent(tempArr[0])
        let val = decodeURIComponent(tempArr[1])
        obj[key] = val
      })
    }
    return obj
  },
  /**
   * 进行md5加密
   */
  md5: function (text) {
    return typeof (text) == "string" ? text.md5(32) : text.toString().md5(32);
  },
  decoratePicSrc: function (content, imgDomain) {
    var reg = /src\s*=\s*['"]([^'"]*?)['"]/;
    var rs_match = content.match(reg);
    if (rs_match && rs_match.length > 1 && rs_match[1].indexOf("http") == -1 && rs_match[1].indexOf("//") != 0) {
      var src = rs_match[0].replace(rs_match[1], imgDomain + rs_match[1]);
      content = content.replace(reg, src);
    }

    return content;
  },
  /**
   * base64转换成url
   */
  base64src(base64data, callback) {
    const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64data) || [];
    if (!format) {
      return (new Error('ERROR_BASE64SRC_PARSE'));
    }
    const fsm = wx.getFileSystemManager();
    const FILE_BASE_NAME = 'tmp_base64src' + util.getRandomString(); //自定义文件名
    const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`;
    const buffer = wx.base64ToArrayBuffer(bodyData);
    fsm.writeFile({
      filePath,
      data: buffer,
      encoding: 'binary',
      success() {
        callback(filePath);
      },
      fail() {
        return (new Error('ERROR_BASE64SRC_WRITE'));
      },
    });
  },
  //京东解析外链css背景图片
  linkParseImg(content,callback){
    getRichText(content).then((res) => {
      callback(res)
    })
  },
  intersectByArray(arrs) {
    var arr = arrs.shift();
    for (var i = arrs.length; i--;) {
      var p = {
          "boolean": {},
          "number": {},
          "string": {}
        },
        obj = [];
      arr = arr.concat(arrs[i]).filter(function (x) {
        var t = typeof x;
        return !((t in p) ? !p[t][x] && (p[t][x] = 1) : obj.indexOf(x) < 0 && obj.push(x));
      });
      if (!arr.length) return null; //发现不符合马上退出
    }
    return arr;
  },
    /**
   * 设置登录前页面的信息
   */
  setBeforeLoginData() {
    // 添加登陆前页面信息，登陆后获取并返回该页面
    let pages = getCurrentPages()
    let thisPage = pages[pages.length - 1]
    let options = jsonToQuery(thisPage.options)
    // 不记录设置页面，防止退出登录后，再次马上登录后跳转到设置页面
    if (thisPage.route == 'packageStore/pages/profile/userSetting/userSetting') {
      return
    }
    let data = {
      route: thisPage.route,
      options: options,
      desc: '记录登录前页面，登陆后返回此页面'
    }
    wx.setStorageSync('login_Redirect_url', data)
  },
  /**
   * 获取登录页前个页面信息
   */
  getBeforeLoginData() {
    let data = wx.getStorageSync('login_Redirect_url')
    if (!data) {
      data = {}
    }
    wx.removeStorageSync('login_Redirect_url')
    return data
  },
  /**
   * 请求是否需要ProjectDir参数
   * @param {String} method 请求的接口
   */
  needForProjectDir (method) {
    let exception = [
      'core.domain.getproprietordomain',
      'social.minappoutline.config'
    ]
    for (let i in exception) {
      if (method.includes(exception[i])) {
        return false
      }
    }
    return true
  },
  /**
   * 登录、退出登录后删除分类缓存
   */
  removeCategoryCache() {
    try {
      const app = getApp()
      app.globalData.pageRefresher.fast = true
      app.globalData.pageRefresher.classify = true
      let localStorage = wx.getStorageInfoSync()
      localStorage.keys.map(item => {
        if(item.includes('all_category_')) {
          removeStorageSync(item)
        }
      })
    } catch (error) {
      
    }
  },
  /**
   * 设置错误日志
   * @param req 请求值
   * @param res 返回值
   */
  setErrorLog (req, res) {
    let errorLog = getStorageSync('errorLog') || []
    let openid = getStorageSync('openid')
    let systemInfo = wx.getSystemInfoSync()
    let data = {
      req,
      res,
      openid,
      systemInfo,
      timeStamp: new Date()
    }
    let str = JSON.stringify(errorLog)
    let size = (str.length * 8) / (1024 * 1024)
    // 粗略估计下缓存大小，如果超过5MB则清空，防止过大导致无法设置
    if (size > 1) {
      console.log('超了AAAAAAAAAAAAAAAAAAAAAAA')
      errorLog = []
    }
    errorLog.push(data)
    setStorageSync('errorLog', errorLog)
  },
  /**
   * 获取错误日志
   */
  getErrorLog () {
    let errorLog = getStorageSync('errorLog') || []
    return errorLog
  },
  /**
   * 清空错误日志
   */
  clearErrorLog () {
    setStorageSync('errorLog', [])
  },
 }

/**
 * 表单处理
 */
const forms = {
  /**
   * 数据有效性验证的正则表达式
   */
  validateRegExp: {
    zh: /[\u4e00-\u9fa5]+/, //验证中文
    en: /^[a-z]+$/, //验证英文
    n: /\d+/, //验证数字
    n_en: /[a-zA-Z][\da-zA-Z_]*/, //验证数字+英文
    zh_en_n: /^[\u4e00-\u9fa5a-zA-Z0-9]+$/, //验证中文+字母+数字
    mobile: /^0?(13|14|15|16|17|18|19)[0-9]{9}$/,
    num: /([+-]?)\d*\.?\d+$/,
    pwd: /^[a-zA-Z0-9]{1}([a-zA-Z0-9]|[._]){5,19}$/,
    p_integer: /^[1-9]\d*$/, //正整数
    price: /^\d*\.?\d*$/,
    address: /^[A-Za-z0-9_()（）\#\-\u4e00-\u9fa5\s]+$/, //地址
    oddNumber: /^\w+$/, //订单号 仅英文和数字
    tel: /(^(([0\+]\d{2,3}-)?(0\d{2,3})-)?(\d{7,8})(-(\d{3,}))?$)|(^(13|15|14|16|17|18|19)[0-9]{9}$)/,
    name: /^[A-Za-z0-9_\-\u4e00-\u9fa5 ]+$/,
    email: /^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*@([A-Za-z0-9]+(?:-[A-Za-z0-9]+)?\.)+[A-Za-z0-9]+(?:-[A-Za-z0-9]+)?$/, //email
    idcard: /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/, //身份证
  },
  /**
   * 获取表单值
   * param: 表单对象
   */
  getValues: function (forms) {
    var f = {};
    var that = this;
    for (var key in forms) {
      var item = forms[key];
      f[key] = item.value;
    }
    return f;
  },
  /**
   * 表单验证
   * param: 表单对象
   */
  formValidate: function (forms) {
    var bo = true;
    for (var key in forms) {
      if (forms[key]) {
        bo = this.validate(forms[key]);
      }
      if (!bo) return false;
    }
    return bo;
  },
  /**
   * 数据有效性验证
   * param: 控件元素
   */
  validate: function (item) {
    if (item.fixed) {
      if (item.fixed != item.value) {
        util.tips(item.error || "请输入正确的格式");
        return false;
      }
    }
    if (item.validate == undefined) return true;
    var arr = item.validate.split('|');
    var bo = true;
    // console.log(arr);
    for (var i in arr) {
      var v = arr[i];
      if (v == "isnull") {
        if (item.value.length <= 0) {
          util.tips(item.error || "请输入正确的格式");
          bo = false;
          return false;
        }
      } else {
        var reg = this.validateRegExp[v];
        if (reg == undefined) continue;
        if (item.value == undefined || item.value == "") continue;
        if (reg.test(item.value) == true) continue;
        else {
          util.tips(item.error || "请输入正确的格式");
          bo = false;
          return false;
        }
      }
    }
    return bo;
  },
  /**
   * 两个输入控件值比较
   */
  compare: function (item1, item2) {
    if (item1.value != item2.value) {
      util.tips("两次输入不一致");
      return false;
    }
    return true;
  },
  /**
   * 解析地址
   */
  address: function (adr) {
    // var address = adr;
    // var proExp = ".+[省]", cityExp = "^.*?[市]", disExp1 = ".+[区]",disExp2 = ".+[县]",disExp3 = ".+[市]";
    // var provinceTemp = address.match(new RegExp(proExp))[0]; // 省
    // var cityTemp = address.match(new RegExp(cityExp))[0]; // 市
    // var district1 = address.match(new RegExp(disExp1)); //区
    // var district2 = address.match(new RegExp(disExp2)); //县
    // var district3 = address.match(new RegExp(disExp3)); //县级市
    // var newAddress = {};
    // if (provinceTemp==null){
    //   newAddress.province="";
    //   newAddress.city = cityTemp;
    //   if (district1 != null) {
    //     district1 = district1[0].replace(cityTemp, ""); //区
    //     newAddress.area = district1;
    //   }
    //   else if(district2 != null){
    //     district2 = district2[0].replace(cityTemp, "");  //县
    //     newAddress.area = district2;
    //   }else{
    //     district3 = district3[0].replace(cityTemp, "");  //县级市
    //     newAddress.area = district3;
    //   }
    // }
    // else{
    //   newAddress.province = provinceTemp;
    //   cityTemp = cityTemp.replace(provinceTemp, ""); // 市
    //   newAddress.city = cityTemp;
    //   if (district1 != null) {
    //     district1 = district1[0].replace(provinceTemp, "").replace(cityTemp, ""); //区
    //     newAddress.area = district1;
    //   }
    //   else if(district2 != null){
    //     district2 = district2[0].replace(provinceTemp, "").replace(cityTemp, "");//县
    //     newAddress.area = district2;
    //   }else{
    //     district3 = district3[0].replace(provinceTemp, "").replace(cityTemp, "");//县级市
    //     newAddress.area = district3;
    //   }
    // }
    // var str = newAddress.province + newAddress.city + newAddress.area;
    // newAddress.detail = address.replace(str,"");
    // console.log(newAddress,'---newAddress');
    // return newAddress;
  }
}

/**
 * Wx缓存存储Storage
 */
const storage = {
  /**
   * 获取缓存中的数据值
   * param: 缓存Key
   * param: 默认值
   */
  get: (key, def) => {
    if (!def) {
      def = null;
    }
    if (!key) {
      return def;
    }
    try{
      var val = getStorageSync(key);
      if (!val) return val;

      var expire = 0;
      if (typeof (val.expire) == "number") {
        expire = val.expire;
      }

      if (expire > 0) {
        var t = new Date(val.timeSpan);
        t.setSeconds(t.getSeconds() + expire);
        var now = new Date();
        if (now > t) {
          return null;
        } else {
          return val.data;
        }
      } else {
        return val.data;
      }
    } catch (e) {
      return def;
    }

  },

  /**
   * 把待缓存数据写入缓存
   * param: 缓存key
   * param: 缓存值
   * param: 时间
   */
  put: (key, val, expire = 1800) => {
    if (!val) return;
    var _data = new Date();
    var t = _data.getTime();
    var data = {
      data: val,
      timeSpan: t,
      expire: expire
    };
    try {
      setStorageSync(key, data)
    } catch (e) { }
  },

  /**
   * 删除指定key的缓存
   * param: 缓存key
   */
  remove: (k) => {
    try {
      wx.removeStorageSync(k);
    } catch (e) {
      // Do something when catch error
    }

  },
  /**
   * 清除所有存在的缓存
   */
  clear: () => {
    wx.clearStorageSync();
  }
};

/**
 * 遮罩层的显示和隐藏
 */
const dialog = {
  /**
   * 显示遮罩层
   * @param {Object} that 页面或组件对象
   * @param {String} key 当前动画名称
   */
  showModal: (that = {}, key = '') => {
    if (isEmpty(key)) {
      key = 'defaultAnimation'
    }
    if (that.data[key]) { // 已经在展示弹窗了就无需再调用弹窗动画
      return
    }
    let animation = wx.createAnimation({
      duration: 200,
      timingFunction: "linear",
      delay: 0
    })
    //that.animation = animation
    animation.translateY(400).step()
    let animationData = that.data.animationData || {}
    animationData[key] = animation.export()
    that.setData({
      animationData,
      [key]: true
    })
    setTimeout(function () {
      animation.translateY(0).step()
      animationData = that.data.animationData || {}
      animationData[key] = animation.export()
      that.setData({
        animationData
      })
    }.bind(that), 200)
  },
  /**
   * 隐藏遮罩层
   * @param {Object} that 页面或组件对象
   * @param {String} key 当前动画名称
   */
  hideModal: (that = {}, key = '') => {
    if (isEmpty(key)) {
      key = 'defaultAnimation'
    }
    let animation = wx.createAnimation({
      duration: 200,
      timingFunction: "linear",
      delay: 0
    })
    animation.translateY(400).step()
    let animationData = that.data.animationData || {}
    animationData[key] = animation.export()
    that.setData({
      animationData
    })
    setTimeout(function () {
      animation.translateY(0).step()
      animationData = that.data.animationData || {}
      animationData[key] = animation.export()
      that.setData({
        animationData,
        [key]: false
      })
    }.bind(that), 200)
  }
}

/**
 * 点击原子操作（连续多次点击，以最后一次为准）
 */
var this_timer_id = null;
const clickIncrement = (fn) => {
  if (typeof this_timer_id != null) {
    clearTimeout(this_timer_id);
  }
  this_timer_id = setTimeout(fn, 200);
}
const clearIncrement = () => {
  if (typeof this_timer_id != null) {
    clearTimeout(this_timer_id);
  }
}

/**
 * 转换富文本数据，将京东的背景图片改为图片
 * @param {String} data 富文本数据
 */
let getRichText = async (data) => {
  data = data || ''
  // 移除多余的空格，防止match函数重复导致卡死（将2个以上的空格改为1个）
  try {
    data = data.replace(/[^\S\n\r\t]{2,}/img, ' ')
  } catch (error) {
    console.log('移除空格失败', error)
  }
  // 获取最前面的style标签内信息
  let matchStyle = data.match(/<style(([\s\S])*?)<\/style>/g)
  let style = ''
  if (matchStyle) {
    style = matchStyle[0]
  }
  let content = data.replace(/<style(([\s\S])*?)<\/style>/g, '')
  let css = ''
  try {
    console.log(content.match(/cssurl="(.*?)"/))
    css = content.match(/cssurl="(.*?)"/)[1]
  } catch (e) {
    console.log(content, e)
  }
  // 有css链接，则去加载css
  console.log(css)
  if (!isEmpty(css)) {
    let cssRes = await downloadCss(`https:${css}`)
    if (!isEmpty(cssRes)) {
      style += cssRes
    }
  }
  // 在 } 后增加换行，后面的match才能生效，否则可能会报错
  style = style.replace(/\}/img, '}\n')
  if (style) {
    let body = content
    // 在 } 后增加换行，后面的style的match才能生效，否则可能会报错
    style = style.replace(/\}/img, '}\n')
    // 在 > 后增加换行，后面的body的match才能生效，否则可能会报错
    body = body.replace(/\>/img, '>\n')
    // 找到每一项style，如： .M123{css内容}
    let match1 = style.match(/\.\S+\{(.+?)*\}/g)
    if (!match1) {
      match1 = []
    }
    // 只有存在url的才需要转换为img
    match1 = match1.filter((item) => {
      return item.includes('url')
    })
    // 找到body中的全部class
    let match2 = body.match(/class=\"(.+?)*\"/g)
    if (!match2) {
      match2 = []
    }
    // 需要匹配的class列表
    let classList = []
    // 获取所有的class等信息，如： <div class='a123 header top' data-id='a123'> 则获取到 ['a123', 'header', 'top']
    match2.map((item) => {
      let arr = item.split('"')
      arr.map((arrItem) => {
        classList = [...classList, ...arrItem.split(' ')]
      })
    })
    // class去重
    classList = Array.from(new Set(classList))
    // 去除class= data-id= 和空的内容
    classList = classList.filter((item) => {
      return item != 'class=' && item != 'data-id=' && item != ''
    })
    // body内没有的class内容的不转换为img
    match1 = match1.filter((item) => {
      let data = item.match(/\.\S+\{/)
      let className = ''
      if (data) {
        className = data[0]
        className = className.substring(1, className.length - 1)
      }
      return classList.includes(className)
    })
    // match1去重，由于同时用了自带的css和网络css，可能导致数据重复，所以需要去重
    match1 = Array.from(new Set(match1))
    // 将match1中的内容转换成img标签中的图片
    let imgList = match1.map((item) => {
      // 获取 .a{background-image:url(xxx.png); height: 100px;} 中的 xxx.png
      item = item.replace(/[\s\S]+url\(/, '')
      item = item.replace(/\)[\s\S]+/, '')
      if (item.length > 0) {
        return `<img style="width:100%;" src="${item}">`
      } else {
        return ''
      }
    })
    imgList = imgList.join('\n')
    content = imgList + content
  }
  return content
}
/**
 * 下载并读取css样式文件
 * @param {String} url css地址
 */
let downloadCss = async (url) => {
  const fileSystemManager = wx.getFileSystemManager()
  return new Promise((resolve, reject) => {
    wx.downloadFile({
      url: url,
      success(res) {
        if (res.statusCode == 200) {
          fileSystemManager.readFile({
            filePath: res.tempFilePath,
            encoding: 'utf8',
            success(res) {
              resolve(res.data)
            },
            fail() {
              resolve('')
            }
          })
        } else {
          resolve('')
        }
      },
      fail(err) {
        console.log('下载css失败', err, url)
        resolve('')
      }
    })
  })
}

/**
 * 跳转登录页面
 * 
 * 使用函数防抖，防止多个接口同时提示跳转
 */
let toLoginPage = debounce((res) => {
  util.alert(res.data.Message, "", function () {
    router.redirect({
      path:'login',
      params:{
        logout:true
      }
    });
  });
}, 3000)

/**
 * 打印接口请求和返回值
 * @param items 请求值
 * @param res 返回值
 */
let logRequest = (items, res) => {
  const app = getApp()
  if (app.globalData.logRequestLevel == 0) {
    return
  }
  try {
    console.groupCollapsed(`====== 请求接口完成 ${items.method || ''} ======`)
    console.log('请求值', items)
    console.log('返回值', res)
    console.log('格式化后的请求值')
    console.log(formatRequestData(items))
    console.log('格式化后的返回值')
    console.log(JSON.stringify(res))
    console.groupEnd()
  } catch (error) {
    console.log('====== 打印数据错误 ======')
    console.log(error)
    console.log(`====== 请求接口 ${items.method || ''} ======`)
    console.log('请求值', items)
    console.log('返回值', res)
    console.log('格式化后的请求值')
    console.log(formatRequestData(items))
    console.log('格式化后的返回值')
    console.log(JSON.stringify(res))
    console.log('====== 打印数据结束 ======')
  }
}

export {
  api,
  util,
  forms,
  storage,
  dialog,
  clickIncrement,
  clearIncrement,
  getSign
}